# @Author:黄景涛
# @Date: 2024/2/21
"""
请求参数的热加载处理、参数回填
"""
import re
from commons.hjt_tools import DebugTalk


class HotLoad:
    dtk = DebugTalk()

    def replace_get_value(self, data):
        """
        :param data:  base_url、url、Cookie、json、params等值
        :return: 热加载回填后的data
        """
        if not data or data is None:
            return data
        try:
            """1.保存原数据的类型"""
            original_type = type(data)

            str_data = str(data)
            # logger.info(f'替换前的request_params：{str_data}')
            """2.热加载替换"""
            str_data = self._hot_loading(str_data)
            # logger.info(f'替换后的request_params：{str_data}')

            """3.还原数据类型"""
            if original_type in (list, dict):
                import ast
                data = ast.literal_eval(str_data)
            else:
                data = original_type(str_data)
            return data
        except Exception:
            raise

    @classmethod
    def _hot_loading(cls, str_data: str):
        """把str_data中，逐一执行每个热加载占位符中的函数，并用函数返回值替换"""

        # 基本匹配 ${func_name(*args)}
        pattern_str = r"\${(?P<func_name>.*?)\((?P<func_args>.*?)\)}"
        # 替换为非字符串 , 如："${len(abc)}"  -> 3
        pattern_object = r"([\"\'])\${(?P<func_name>.*?)\((?P<func_args>.*?)\)}\1"

        '''5.返回值的类型，回填'''
        try:
            str_data = re.sub(pattern_str, cls.replace_function, str_data)
        except Exception as e:
            # print(f'异常信息：{str(e)}')
            raise
            # str_data = re.sub(pattern_object, lambda match:str(cls.replace_function(match)), str_data)
        # # print(f'替换结束！\n')
        return str_data

    @classmethod
    def replace_function(cls, match):
        #     '''1.提取函数名称、函数的参数'''
        #     # print(f'\n开始替换：')
        #     # print(f'函数位置：{hot_word}')
        func_expr = match.group()
        func_name = match.group('func_name')
        func_args = match.group('func_args')
        # print(f'提取结果：{match.groups()}')
        # print(f'提取的函数名：{func_name}')

        '''2.处理参数'''
        func_args = cls.args_(func_args)

        '''3.处理函数对象'''
        try:
            # 从hjt_tools中执行自定义函数
            func_obj = getattr(HotLoad.dtk, func_name)
            # print(f'自定义函数：{func_obj}')
        except AttributeError:
            try:
                func_obj = __builtins__.get(func_name)
                # print(f'内置函数：{func_obj}')
            except AttributeError:
                error_msg = f'不存在函数【{func_name}】'
                raise Exception(error_msg)

        '''4.调用函数'''
        try:
            return_info = func_obj(*func_args)
        except Exception as e:
            args_error_msg = f'函数【{func_name}】执行报错，<{e.__class__.__name__}>:{e} ——— 热加载的数据: {func_expr}'
            raise Exception(args_error_msg)

        # print(f'函数执行：{return_info}')
        # print(f'返回值类型：{type(return_info)}')
        return return_info

    @classmethod
    def args_(cls, func_args: str):
        """2.处理参数"""
        try:
            func_args = eval(func_args)
            # 处理非元组，如：'abc'、[1,2,3]、{'a':1, 'b':2}
            if not isinstance(func_args, tuple):
                func_args = (func_args,)
        except (SyntaxError, NameError):
            # 兼容处理：参数未加引号
            func_args = (func_args,)

        # 处理('',)
        if func_args[0] == '':
            func_args = tuple()

        # print(f'提取的参数：{(arg for arg in func_args)}')
        return func_args


if __name__ == '__main__':
    getattr(__builtins__, 'len')
